package com.jsb.laundry.service.impl;

import com.jsb.laundry.common.constant.CommonConstants;
import com.jsb.laundry.common.constant.JSBSpecialID;
import com.jsb.laundry.common.enums.OrderStatus;
import com.jsb.laundry.common.enums.UserAddressCity;
import com.jsb.laundry.common.enums.UserAddressCityTown;
import com.jsb.laundry.common.enums.UserAddressRegion;
import com.jsb.laundry.common.utils.JSBUtil;
import com.jsb.laundry.common.utils.baidu.CalLngLatUtil;
import com.jsb.laundry.common.utils.sf.SFMsgDataBuilder;
import com.jsb.laundry.common.utils.sf.SFServiceCodeEnum;
import com.jsb.laundry.common.utils.sf.SFUtil;
import com.jsb.laundry.common.utils.sf.dto.FactoryInfoDto;
import com.jsb.laundry.common.utils.sf.dto.UserInfoDto;
import com.jsb.laundry.dao.OrderDao;
import com.jsb.laundry.model.dto.PayModeRequest;
import com.jsb.laundry.model.dto.ShopsLngLatDto;
import com.jsb.laundry.model.entity.*;
import com.jsb.laundry.model.vo.ConfirmOrderPageVo;
import com.jsb.laundry.service.OrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Resource
    private OrderDao orderDao;

    @Value("${jsb.config.filter.banUser}")
    private List banUser = new ArrayList<>();

    @Override
    public ConfirmOrderPageVo calOrderGoodsInfo(PayModeRequest payModeRequest) {
        String userId = payModeRequest.getUserId();
        String cardId = payModeRequest.getCardId();
        List<PayModeRequest.OrderInfo> orderInfoList = payModeRequest.getOrderInfoList();
        if (JSBUtil.isEmptyCollection(orderInfoList)) {
            return new ConfirmOrderPageVo();
        }

        //购买的商品id
        List<String> goodsId = orderInfoList.stream()
                .map(PayModeRequest.OrderInfo::getGoodsId).collect(Collectors.toList());

        //获取服务对应的价格
        List<ConfirmOrderPageVo.OrderInfoVo> orderGoodsInfo = orderDao.getOrderGoodsInfo(orderInfoList);
        //同步laundryInfo的购买量
        orderGoodsInfo.forEach(var0 -> orderInfoList.stream()
                .filter(detail -> detail.getServeId().equals(var0.getServeId()))
                .findFirst()
                .ifPresent(detail -> var0.setBuyNum(detail.getBuyNum())));

        // 总购买量
        int buyNumTotal = 0;
        //原价
        int originalPrice = 0;
        //计算实际支付total
        int total = 0;
        for (ConfirmOrderPageVo.OrderInfoVo var2 : orderGoodsInfo) {
            int servePrice = Integer.parseInt(var2.getServePrice());
            int buyNum = var2.getBuyNum();

            int payPrice = servePrice * buyNum;
            total += payPrice;
            originalPrice += payPrice;

            //当前服务数据库int价格转double展示
            var2.setOriginalPrice(JSBUtil.turnDoubleStr(String.valueOf(payPrice)));
            var2.setTotal(JSBUtil.turnDoubleStr(String.valueOf(payPrice)));
            var2.setServePrice(JSBUtil.turnDoubleStr(String.valueOf(servePrice)));
            //当前订单总购买件数
            buyNumTotal += buyNum;
        }

        /**
         * 使用了优惠券
         */
        if (!JSBUtil.isEmptyString(cardId) && !(JSBSpecialID.JSB_MONTH_1_298.equals(goodsId.get(0))
                || JSBSpecialID.JSB_MONTH_2_398.equals(goodsId.get(0)))) {
            //获取用户使用的优惠券的面值
            int cardFaceValue = orderDao.findCoupon(userId, cardId);
            if (total > cardFaceValue) {
                total -= cardFaceValue;
            } else {
                LOGGER.info("订单:[{}]金额不满足优惠券使用要求", payModeRequest);
            }
        }

        ConfirmOrderPageVo confirmOrderPageVo = new ConfirmOrderPageVo();

        confirmOrderPageVo
                .setTotal(JSBUtil.turnDoubleStr(String.valueOf(total)))     //实付金额
                .setOriginalPrice(JSBUtil.turnDoubleStr(String.valueOf(originalPrice))) // 原价
                .setDiscountTotal(JSBUtil.turnDoubleStr(String.valueOf(originalPrice - total))) //优惠金额
                .setBuyNumTotal(String.valueOf(buyNumTotal)) //总购买量
                .setEquityExplain(orderGoodsInfo.get(0).getEquityExplain()) //权益
                .setServeInfo(orderGoodsInfo)// 详细信息
        ;

        return confirmOrderPageVo;
    }

    @Override
    public int updParentOrderInfo(JsbOrders parentOrder) {
        String userId = parentOrder.getUserId();
        String orderId = parentOrder.getOrderId();
//        JsbOrders order = getOrderToShopOrFactory(parentOrder);
        JsbOrdersShippingAddresses userAddress = parentOrder.getUserAddress();

        parentOrder.setShippingType("1");
        JsbOrders orderToShop = getOrderToShopOrFactory(parentOrder);
        double shopsDistance = orderToShop.getDistance();
        String shopsId = orderToShop.getShopIdOrFactoryId();
//        String userXY = CalLngLatUtil.getLngLat(userAddress.getPickupAddress());
//        //我国：lng:经度(大)，lat:维度(小)
//        String[] lng_lat = userXY.split(",");
////        String[] lat_lng = {lng_lat[1], lng_lat[0]};
//
//        //TODO 计算出最优距离店铺
//        String shopsId = null;
//        double shopsDistance = Double.MAX_VALUE;
//        // 查询出所有洗衣店铺经纬度
//        List<ShopsLngLatDto> list = orderDao.findAllLaundryShops();
//        //查询工厂位置计算距离，6km内给小哥，否则派给顺丰
////        List<ShopsLngLatDto> list = orderDao.findAllLaundryShopsFactory();
//        for (ShopsLngLatDto shopsLngLat : list) {
//            String pointXY = shopsLngLat.getPointXY();
//            String[] split = pointXY.split(",");
//            double distance = CalLngLatUtil.getDistance(Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(lng_lat[0]), Double.parseDouble(lng_lat[1]));
//            // 保存最近距离和店铺ID
//            if (distance < shopsDistance) {
//                shopsDistance = distance;
//                shopsId = shopsLngLat.getShopsId();
//            }
//        }

        UserInfo userInfo1 = orderDao.findUserInfoByUserId(userId);

        /**
         * TODO 禁止一些内部用户单子走顺丰
         */
        if (banUser.contains(userInfo1.getUserPhone())) {
            shopsDistance = -1;
        }

        JsbOrders parentOrder1 = new JsbOrders();
        parentOrder1.setOrderId(orderId).setShopId(shopsId).setOrderStatus(OrderStatus.SUCCESS_PAY.getCode());

        /**
         * 若最优距离大于6km,则将订单派送给顺丰,shopsId赋值为工厂的id,
         * 若有多个工厂，再选出最近的工厂，返回信息
         *
         * TODO 对接顺丰
         *
         */
        if (shopsDistance > 6) {
            // 获取用户信息
            UserInfoDto userInfo = new UserInfoDto();
            //获取商品id
            List<String> goodsId = parentOrder.getSubOrderList().stream().map(JsbOrdersItem::getProductId).collect(Collectors.toList());
            //获取是否购买过优惠券
            Boolean buyCouponEd = orderDao.buyCouponEd(userId);
            userInfo.setBuyCouponEd(buyCouponEd).setGoodsId(goodsId.get(0))
                    .setUserAddress(userAddress.getPickupAddress()).setUserPhone(userAddress.getPickupMobile()).setUserName(userAddress.getPickupName())
                    .setAppointmentTime(parentOrder.getAppointmentTime()).setGoodsId(goodsId.get(0));


            //获取工厂信息
//            List<ShopsLngLatDto> factoryList = orderDao.findFactory();
//            shopsId = factoryList.get(0).getShopsId();
            parentOrder.setShippingType("2");
            JsbOrders orderToShopId = getOrderToShopOrFactory(parentOrder);
            shopsId = orderToShopId.getShopIdOrFactoryId();

            FactoryInfoDto factoryInfo = orderDao.getLaundryFactoryInfo(shopsId);
            String city = UserAddressCity.findCityById(factoryInfo.getCityId());
            String town = UserAddressCityTown.findCityById(factoryInfo.getCityTownId());
            String region = UserAddressRegion.findCityById(factoryInfo.getRegionId());
            factoryInfo.setFactoryAddress(city + town + region + factoryInfo.getDetailAddress());

            //顺丰下单信息
            String orderMsgData = SFMsgDataBuilder.getCreateOrderMsgData(orderId, userInfo, factoryInfo, "0", goodsId.size());
            //下单返回的信息
            String sfResponse = SFUtil.SFRequest(SFServiceCodeEnum.EXP_RECE_CREATE_ORDER.name(), orderMsgData);
            //解析出来的顺丰单号
            String sfWaybillNo = SFUtil.getSFWaybillNo(sfResponse);

            //支付成功后更新订单的信息 （支付成功后，订单分配给顺丰时更新状态）shopsId, orderId, sfWaybillNo
            parentOrder1.setShippingType("2");
            if (!buyCouponEd) { //没有购买vip邮费20
                parentOrder1.setShippingPrice(CommonConstants.POST_PRICE);
            }

            //物流信息
            JsbOrdersFulfillment jsbOrdersFulfillment = new JsbOrdersFulfillment();
            jsbOrdersFulfillment.setOrderId(orderId).setTrackingNumber(sfWaybillNo)
                    .setTrackingCompany("顺丰物流").setTrackingCode("SF").setTrackingDirection(1)
                    .setPickupAddress(userAddress.getPickupAddress()).setDeliveryAddress(factoryInfo.getFactoryAddress())
                    .setCustomerName(userAddress.getPickupName()).setCustomerTel(userAddress.getPickupMobile());

            orderDao.updOrderFlowOfSF(jsbOrdersFulfillment); //更新物流信息
            parentOrder1.setOrderStatus(OrderStatus.ORDER_RECEIVED.getCode());
            orderDao.updParentOrderInfo(parentOrder1); //更新父订单状态
            //顺丰就直接入工厂表
            /**
             * 订单入工厂表 jsb_orders_factory、jsb_orders_factory_item
             */
            orderEnterFactory(orderId);

            return 1;
        }

        //支付成功后，订单分配给商铺时更新状态
        parentOrder1.setShippingType("1");
        return orderDao.updParentOrderInfo(parentOrder1);
    }

    /**
     * 获取订单将要去哪个小站、工厂(1去店铺、2去工厂)
     *
     * @return
     */
    private JsbOrders getOrderToShopOrFactory(JsbOrders parentOrder) {
        JsbOrders order = new JsbOrders();

        if ("1".equals(parentOrder.getShippingType())) { //快递方式：1 小哥去小站(匹配最近店铺)

            JsbOrdersShippingAddresses userAddress = parentOrder.getUserAddress();
            String userXY = CalLngLatUtil.getLngLat(userAddress.getPickupAddress());
            //我国：lng:经度(大)，lat:维度(小)
            String[] lng_lat = userXY.split(",");

            //TODO 计算出最优距离店铺
            String shopsId = null;
            double shopsDistance = Double.MAX_VALUE;
            // 查询出所有洗衣店铺经纬度
            List<ShopsLngLatDto> list = orderDao.findAllLaundryShops();
            //查询工厂位置计算距离，6km内给小哥，否则派给顺丰
//            List<ShopsLngLatDto> list = orderDao.findAllLaundryShopsFactory();
            for (ShopsLngLatDto shopsLngLat : list) {
                String pointXY = shopsLngLat.getPointXY();
                String[] split = pointXY.split(",");
                double distance = CalLngLatUtil.getDistance(Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(lng_lat[0]), Double.parseDouble(lng_lat[1]));
                // 保存最近距离和店铺ID
                if (distance < shopsDistance) {
                    shopsDistance = distance;
                    shopsId = shopsLngLat.getShopsId();
                }
            }
            if (list != null) {
                order.setShopIdOrFactoryId(shopsId).setDistance(shopsDistance);
            }
        } else if ("2".equals(parentOrder.getShippingType())) { // 2 快递去工厂(匹配最近工厂)
            JsbOrdersShippingAddresses userAddress = parentOrder.getUserAddress();
            String userXY = CalLngLatUtil.getLngLat(userAddress.getPickupAddress());
            //我国：lng:经度(大)，lat:维度(小)
            String[] lng_lat = userXY.split(",");

            //TODO 计算出最优工厂距离
            String shopsId = null;
            double shopsDistance = Double.MAX_VALUE;
            //查询工厂位置计算距离，6km内给小哥，否则派给顺丰
            List<ShopsLngLatDto> list = orderDao.findAllLaundryShopsFactory();
            for (ShopsLngLatDto shopsLngLat : list) {
                String pointXY = shopsLngLat.getPointXY();
                String[] split = pointXY.split(",");
                double distance = CalLngLatUtil.getDistance(Double.parseDouble(split[0]), Double.parseDouble(split[1]), Double.parseDouble(lng_lat[0]), Double.parseDouble(lng_lat[1]));
                // 保存最近距离和店铺ID
                if (distance < shopsDistance) {
                    shopsDistance = distance;
                    shopsId = shopsLngLat.getShopsId();
                }
            }
            if (list != null) {
                order.setShopIdOrFactoryId(shopsId).setDistance(shopsDistance);
            }

        }
        return order;
    }


    /**
     * 订单入工厂表 jsb_orders_factory、jsb_orders_factory_item
     */
    private void orderEnterFactory(String payId) {
        JsbOrdersFactory jsbOrdersFactory = orderDao.getOrdersFactoryInfo(payId);
        if (jsbOrdersFactory == null) { //不存在时，则入库

            /**
             * 入工厂表 jsb_orders_factory
             */
            JsbOrders orderInfo = orderDao.getOrderInfo(payId);
            JsbOrdersFactory ordersFactory = new JsbOrdersFactory();
            ordersFactory.setOrderId(payId).setUserId(orderInfo.getUserId()).
                    setFactoryId(orderInfo.getShopId())
                    .setFactoryOrdersStatus(1).setType(orderInfo.getShippingType());
            Integer var0 = orderDao.addOrderFactory(ordersFactory);


            /**
             * 入工厂表 jsb_orders_factory_item
             */
            List<JsbOrdersItem> subOrderList = orderDao.getSubOrderList(payId);
            List<JsbOrdersFactoryItem> jsbOrdersFactoryItem = subOrderList.stream()
                    .map(jsbOrdersItem -> {
                        JsbOrdersFactoryItem item = new JsbOrdersFactoryItem();
                        item.setOrderFactoryId(var0)
                                .setProductId(jsbOrdersItem.getProductId())
                                .setOrderId(jsbOrdersItem.getOrderId())
                                .setSubOrderId(jsbOrdersItem.getSubOrderId());
                        return item;
                    })
                    .collect(Collectors.toList());

            int var1 = orderDao.addOrderFactoryItem(jsbOrdersFactoryItem);
        }
    }

    @Override
    public List diffOrderStatusNum(String userId) {
        // 创建list长度为10，默认填充0
        List<Integer> returnList = new ArrayList<>(Collections.nCopies(20, 1));
//        List<DiffOrderStatusNumDto> list = orderDao.diffOrderStatusNum(userId);
        // 把list对应位置存入订单状态的数量
//        for (int i = 0; i < list.size(); i++) {
//            if () {
//
//            }
////            int status = diffOrderStatus(list.get(i).getOrderDirection(), list.get(i).getOrderStatus());
//            returnList.set(status, returnList.get(status) + list.get(i).getNum());
//        }
        // 移除不需要展示的状态
//        returnList.remove(returnList.size() - 1);
        return returnList;
    }
}
